﻿#ifndef H264PARSER_H
#define H264PARSER_H

#include <QObject>
#include <QImage>

#ifdef _WIN32
//Windows
extern "C"
{
#include <libavformat/avformat.h>
#include <libavutil/mathematics.h>
#include <libavutil/time.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavformat/avformat.h>
#include <libavutil/mathematics.h>
#include <libavutil/time.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#ifdef __cplusplus
};
#endif
#endif

class H264Parser : public QObject
{
    Q_OBJECT
public:
    explicit H264Parser(QObject *parent = nullptr);
    ~H264Parser();

public:
    void inputData(const QByteArray& input);

    /**
     * @brief parserPacket 拼h264裸流数据
     * @param input
     * @return 返回完整的AVPacket列表
     */
    QList<AVPacket*> parserPacket();

    /**
     * @brief decodePacket2Frame 将AVPacket转为AVFrame
     * @param pkt
     * @return
     */
    int decodePacket2Frame(const AVPacket& pkt, int& imageWidth, int& imageHeight);

    /**
     * @brief decodeFrame2QImage  将AVFrame转为QImage图像
     * @param frame
     * @return
     */
    QImage decodeFrame2QImage(const AVFrame& frame);

    /**
     * @brief create_sei_nal_unit  创建SEI NAL单元
     * @param sei_text
     * @param sei_size
     * @return
     */
    uint8_t* create_sei_nal_unit(const char* sei_text, int* sei_size);

    /**
     * @brief insert_sei_into_packet 在关键帧AVPacket之前插入SEI
     * @param pkt       帧AVPacket
     * @param sei_text  SEI段自定义数据
     * @return
     */
    int insert_sei_into_packet(AVPacket* pkt, const char* sei_text);

    /**
     * @brief is_h264_keyframe 是否为关键帧
     * @param data
     * @param size
     * @return
     */
    bool is_h264_keyframe(const uint8_t *data, int size);

signals:


private:
    // H264解码器
    AVCodec *h264_codec_;
    AVCodecParserContext *h264_parser_;
    AVCodecContext *h264_codec_ctx_;

    // JEPG
//    AVCodec *jpeg_codec_;
//    AVCodecContext *jpeg_ctx_;
    int image_width = 0;
    int image_height = 0;

private:
    QByteArray h264Catche;
};

#endif // H264PARSER_H
